﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json.Serialization;
using Sustainalytics.ESGRatings.DataContract.ESG;
using Xunit;

namespace Sustainalytics.ESGComputing.Service.Tests
{
    public class ComputingBenchmarks:Disposable
    {
        private static ESGRatingsOptionsDto _options;

        private static JsonMediaTypeFormatter _jsonMediaTypeFormatter;
        readonly string _httpLocalhostEsgcomputingservApiV1Esgcompute = "http://localhost:10280/esgcomputingserv/api/v1/esgcompute";

        private bool _disposed;

        public  ComputingBenchmarks()
        {
            _options = new ESGRatingsOptionsDto
            {
                MatrixId = Guid.Parse("290a624d-a1bf-4298-b91d-2456223923d5 "),
                RefUnivId = Guid.Parse("71f2972e-3153-4f83-ac6e-d82bd676481f "),
                //Include = ESGRatingsOptions.IncludeFlags.IncludeAggregatedScores | ESGRatingsOptions.IncludeFlags.IncludeIndWeightedScores | ESGRatingsOptions.IncludeFlags.IncludeRatings,
            };

            _jsonMediaTypeFormatter = new JsonMediaTypeFormatter
            {
                SerializerSettings = { ContractResolver = new CamelCasePropertyNamesContractResolver() }
            };
             //HttpClient _client = new HttpClient();

            //var task = _client.PostAsync("http://localhost:10280/esgcomputingserv/api/v1/esgcompute/statistics",
            //     new ComputeStatisticsOptions() { ComputationContextDetails = "resetStatistics", ResetStatistics = true }
            // , _jsonMediaTypeFormatter);
            //task.Result.EnsureSuccessStatusCode();
        }

        [Fact]
        public void GetRatingsBenchmarks_1_CallTest()
        {
            HttpClient _client = new HttpClient();
            _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

           //var result= _client.PostAsync("http://localhost:10280/esgcomputingserv/api/v1/esgcompute/statistics",
           //     new ComputeStatisticsOptions() {ComputationContextDetails = "One call", ResetStatistics = false}
           // , _jsonMediaTypeFormatter)
           //  .ContinueWith (_1=> _client.PostAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute, _options,
           //     _jsonMediaTypeFormatter)
           //     .ContinueWith(
           //         _2 => _client.GetAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute))
           //  );

           // //_client.GetAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute);
           // Assert.IsTrue(result.Result.Result.Result.StatusCode == HttpStatusCode.OK);


            var result = _client.PostAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute, _options,
                _jsonMediaTypeFormatter);

            Assert.True(result.Result.StatusCode==HttpStatusCode.OK);

        }


        [Fact]
        public void GetRatingsBenchmarks_25_SequentialCallsTest()
        {
            int MaxCalls = 25;
            HttpClient _client = new HttpClient();
            _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            _client.PostAsync("http://localhost:10280/esgcomputingserv/api/v1/esgcompute/statistics",
                new ComputeStatisticsOptions() {ComputationContextDetails =String.Format( "{0} sequential Calls",MaxCalls), ResetStatistics = false}
                , _jsonMediaTypeFormatter).Result.EnsureSuccessStatusCode();

            var bResult = true;
            for (int i = 0; i < MaxCalls; i++)
            {
                var result = _client.PostAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute, _options,
                    _jsonMediaTypeFormatter);
                bResult  =bResult && result.Result.StatusCode == HttpStatusCode.OK;
            }
            _client.GetAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute).Result.EnsureSuccessStatusCode();
            _client.Dispose();
            Assert.True(bResult);
        }


        [Fact]
        public void GetRatingsBenchmarks_2_SimultaneousCalls()
        {
            List<bool> results = new List<bool>();
            HttpClient client = new HttpClient();
            var exclusive = 2;
            client.PostAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute + "/statistics",
               new ComputeStatisticsOptions() { ComputationContextDetails = String.Format("{0} parallel Calls", exclusive), ResetStatistics = false }
               , _jsonMediaTypeFormatter).Result.EnsureSuccessStatusCode();
            Parallel.For(0, exclusive, (i) =>
            {
                try
                {
                    results.Add(WebAQuery());
                }
                catch (Exception ex)
                {
                    Debug.Write(ex.ToString());
                }
            });
            client.Dispose();
            Assert.True(results.All(x=>x));
        }

        [Fact]
        public void GetRatingsBenchmarks_5_SimultaneousCalls()
        {
            List<bool> results = new List<bool>();
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var exclusive = 5;
            client.PostAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute+"/statistics",
               new ComputeStatisticsOptions() { ComputationContextDetails = String.Format("{0} parallel Calls", exclusive), ResetStatistics = false }
               , _jsonMediaTypeFormatter).Result.EnsureSuccessStatusCode();

           
            var isCompleted =Parallel.For(0, exclusive, (i) =>
            {
                try
                {
                    var task = client.PostAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute, _options, _jsonMediaTypeFormatter);
                    results.Add( task.Result.StatusCode == HttpStatusCode.OK);
                }
                catch (Exception ex)
                {
                    Debug.Write(ex.ToString());
                }
            }).IsCompleted;
            if (isCompleted)
            client.GetAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute);
          
            Assert.True(results.All(x => x));
            client.Dispose();
        }

        private bool WebAQuery()
        {
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var task = client.PostAsync(_httpLocalhostEsgcomputingservApiV1Esgcompute, _options, _jsonMediaTypeFormatter);

            return task.Result.StatusCode == HttpStatusCode.OK;

        }
    }
}